/***********************************************************************************************************************
**	filename: cfg_info.c
**	author: Echo Zhang @2021-05-23
**  e-mail: not_xx@126.com
***********************************************************************************************************************/
#include "dbg.h"
#include "cfg_info.h"
#include "cJSON.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static bool _process_mqtt_info_conf(cJSON *jsonData, struct mqtt_info *mqttCfg)
{
    int num = cJSON_GetArraySize(jsonData);

    if(num < 4) {
        return false;
    }
    strcpy(mqttCfg->addr, cJSON_GetArrayItem(jsonData, 0)->valuestring);
    mqttCfg->port = cJSON_GetArrayItem(jsonData, 1)->valueint;
    strcpy(mqttCfg->user, cJSON_GetArrayItem(jsonData, 2)->valuestring);
    strcpy(mqttCfg->passwd, cJSON_GetArrayItem(jsonData, 3)->valuestring);

    return true;
}


static cJSON *_save_mqtt_info_conf(struct mqtt_info *mqttCfg)
{
    cJSON *arrayJson = cJSON_CreateArray();
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(mqttCfg->addr));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateNumber(mqttCfg->port));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(mqttCfg->user));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(mqttCfg->passwd));
    return arrayJson;
}

static bool _process_dial_info_conf(cJSON *jsonData, struct dial_apn *dialCfg)
{
    int num = cJSON_GetArraySize(jsonData);
    if (num < 3) {
        return false;
    }

    strcpy(dialCfg->apn, cJSON_GetArrayItem(jsonData, 0)->valuestring);
    strcpy(dialCfg->user, cJSON_GetArrayItem(jsonData, 1)->valuestring);
    strcpy(dialCfg->passwd, cJSON_GetArrayItem(jsonData, 2)->valuestring);

    return true;
}

static cJSON *_save_dial_info_conf(struct dial_apn *_cfgInfo)
{
    cJSON *arrayJson = cJSON_CreateArray();
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(_cfgInfo->apn));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(_cfgInfo->user));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(_cfgInfo->passwd));
    return arrayJson;
}

static bool _process_serial_info_conf(cJSON *jsonData, struct serial_info *serialCfg)
{
    int num = cJSON_GetArraySize(jsonData);
    if (num < 6) {
        return false;
    }

    strcpy(serialCfg->name, cJSON_GetArrayItem(jsonData, 0)->valuestring);
    serialCfg->baud = cJSON_GetArrayItem(jsonData, 1)->valueint;
    serialCfg->databit = cJSON_GetArrayItem(jsonData, 2)->valueint;
    serialCfg->stopbit = cJSON_GetArrayItem(jsonData, 3)->valueint;
    serialCfg->parity = cJSON_GetArrayItem(jsonData, 4)->valueint;
    serialCfg->flow = cJSON_GetArrayItem(jsonData, 5)->valueint;

    return true;
}

static cJSON *_save_serial_info_conf(struct serial_info *_cfgInfo)
{
    cJSON *arrayJson = cJSON_CreateArray();
    cJSON_AddItemToArray(arrayJson, cJSON_CreateString(_cfgInfo->name));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateNumber(_cfgInfo->baud));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateNumber(_cfgInfo->databit));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateNumber(_cfgInfo->stopbit));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateNumber(_cfgInfo->parity));
    cJSON_AddItemToArray(arrayJson, cJSON_CreateNumber(_cfgInfo->flow));
    return arrayJson;
}

bool cfg_info_load(const char *filename, struct cfg_info *cfgInfo)
{
    FILE *fp = fopen(filename, "r");
    if(fp == NULL) {
        return false;
    }
    char buffer[1024*100];
    int len = fread(buffer, 1, sizeof(buffer)-1, fp);
    fclose(fp);
    if(len < 0) {
        return false;
    }
    buffer[len] = 0;
    cJSON *root = cJSON_Parse(buffer);
    if(root == NULL) {        
        return false;
    }

    cJSON *debugData = cJSON_GetObjectItem(root, "debug");
    if (NULL != debugData) {
        cfgInfo->isDebugOut = debugData->valueint;
        dbg_msg("Debug switch:%d", cfgInfo->isDebugOut);
    }

    cJSON *deviceId = cJSON_GetObjectItem(root, "device_id");
    if (NULL != deviceId) {
        cfgInfo->device_id = deviceId->valuestring;
        dbg_msg("读取设备ID:%s", cfgInfo->device_id);
    } else {
        cfgInfo->device_id = NULL;
    }

    cJSON *mqttJson = cJSON_GetObjectItem(root, "mqtt_info");
    if(mqttJson != NULL) {
        _process_mqtt_info_conf(mqttJson, cfgInfo->mqttCfg);
    } 

    cJSON *dialJson = cJSON_GetObjectItem(root, "dial_info");
    if(dialJson != NULL) {
        _process_dial_info_conf(dialJson, cfgInfo->dialCfg);
    } 

    cJSON *serialJson = cJSON_GetObjectItem(root, "serial_info");
    if(serialJson != NULL) {
        _process_serial_info_conf(serialJson, cfgInfo->serialCfg);
    } 

    return true;
}

bool cfg_info_save(const char *filename, const struct cfg_info *cfgInfo)
{
    cJSON *root = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "mqtt_info", _save_mqtt_info_conf(cfgInfo->mqttCfg));
    cJSON_AddItemToObject(root, "dial_info", _save_dial_info_conf(cfgInfo->dialCfg));
    cJSON_AddItemToObject(root, "serial_info", _save_serial_info_conf(cfgInfo->serialCfg));
    cJSON_AddItemToObject(root, "device_id", cJSON_CreateString(cfgInfo->device_id));
    cJSON_AddItemToObject(root, "debug", cJSON_CreateBool(cfgInfo->isDebugOut));

    FILE *fp = fopen(filename, "w");
    if(fp != NULL) {
        char *string = cJSON_Print(root);
        fprintf(fp, "%s", string);
        free(string);
        fclose(fp);
        dbg_msg("配置文件保存完成！");
    } else {
        dbg_err("配置文件[%s]保存失败！~", filename);
    }
    free(root);
#ifdef __arm__
    system("sync");
#endif
    return fp!=NULL;
}

void print_config(const struct cfg_info *cfgInfo)
{
    dbg_msg("============= Load Config ===============");
    dbg_msg("******** MQTT info ********");
    dbg_msg("address: %s", cfgInfo->mqttCfg->addr);
    dbg_msg("port: %d", cfgInfo->mqttCfg->port);
    dbg_msg("user: %s", cfgInfo->mqttCfg->user);
    dbg_msg("passwd: %s", cfgInfo->mqttCfg->passwd);
    dbg_msg("******** Dial info ********");
    dbg_msg("apn: %s", cfgInfo->dialCfg->apn);
    dbg_msg("user: %s", cfgInfo->dialCfg->user);
    dbg_msg("passwd: %s", cfgInfo->dialCfg->passwd);
    dbg_msg("******** Serial info ******");
    dbg_msg("port: %s", cfgInfo->serialCfg->name);
    dbg_msg("baudRate: %d", cfgInfo->serialCfg->baud);
    dbg_msg("databit: %d", cfgInfo->serialCfg->databit);
    dbg_msg("stopbit: %d", cfgInfo->serialCfg->stopbit);
    dbg_msg("parity: %d", cfgInfo->serialCfg->parity);
    dbg_msg("flowctrl: %d", cfgInfo->serialCfg->flow);
    dbg_msg("******** config info ******");
    dbg_msg("debug: %d", cfgInfo->isDebugOut);
    dbg_msg("device_id: %s", cfgInfo->device_id);
    dbg_msg("========================================");   
}


/***********************************************************************************************************************
**	endline
***********************************************************************************************************************/
